home *** CD-ROM | disk | FTP | other *** search
/ The Arsenal Files 4 / The Arsenal Files 4 (Arsenal Computer).ISO / casm / au116-as.exe / UTIL / GETREC.CPP < prev    next >
C/C++ Source or Header  |  1994-11-15  |  31KB  |  1,434 lines

  1. #include "..\au.hpp"
  2.  
  3. #include <time.h>
  4.  
  5. #define SZ_NAME 80
  6.  
  7. /***********************************************************************/
  8. #if SUPPORT_DWC || SUPPORT_LZH || SUPPORT_HA
  9. static void my_localtime(time_t t, ARC_RECORD *r)
  10. {
  11.     struct tm *tm;
  12.  
  13.     tm = localtime(&t);           // Expensive function, costs 4K
  14.     r->date.year  = tm->tm_year;
  15.     r->date.month = tm->tm_mon;
  16.     r->date.day   = tm->tm_mday;
  17.     r->hour       = tm->tm_hour;
  18.     r->min          = tm->tm_min;
  19.     r->sec          = tm->tm_sec;
  20.  
  21.     r->date.month++;
  22.     if (r->date.month == 13)
  23.     {
  24.         r->date.month = 1;
  25.         r->date.year++;
  26.     }
  27. }
  28. #endif
  29. /***********************************************************************/
  30. void ARC_HANDLE::fill_date(ARC_RECORD *record)
  31. {
  32.     unsigned char d1,d2;
  33.  
  34.     d1 = read_char();
  35.     d2 = read_char();
  36.     record->date.year  = ((d2 & 0xFE) >> 1) + 1980;
  37.     record->date.month = (d2 & 0x01)*8 + ((d1 & 0xE0) >> 5);
  38.     record->date.day   = (d1 & 0x1F);
  39. }
  40. /***********************************************************************/
  41. void ARC_HANDLE::fill_time(ARC_RECORD *record)
  42. {
  43.     unsigned char d1,d2;
  44.  
  45.     d1 = read_char();
  46.     d2 = read_char();
  47.     record->hour = (d2 & 0xF8) >> 3;
  48.     record->min = (d2 & 0x07)*8 + ((d1 & 0xE0) >> 5);
  49.     record->sec = (d1 & 0x1F) * 2;
  50. }/****************************************************************/
  51. #if SUPPORT_ARC
  52. int ARC_HANDLE::get_record_arc7(ARC_RECORD *record, char *name)
  53. {
  54.     int ch;
  55.     char string[255];
  56.  
  57.     if (pos == 0)
  58.     {
  59.         pos+=29;
  60.         for (;;)
  61.         {
  62.             seek(pos, SEEK_SET);
  63.             ch = read_char();
  64.             pos+=ch;
  65.             seek(pos+1, SEEK_SET);
  66.             ch = read_char();
  67.             if (ch != 0)
  68.                 break;
  69.         }
  70.     }
  71.     for (;;)
  72.     {
  73.        seek(pos+1, SEEK_SET);
  74.        ch = read_char();
  75.        switch (ch)
  76.        {
  77.           case EOF:
  78.           case 0:
  79.              return EOF;
  80.           case 2:
  81.              record->method = 1; break;
  82.           case 8:
  83.              record->method = 3; break;
  84.           case 10:
  85.              record->method = 25; break;
  86.           case 21:
  87.              pos += 15;
  88.              seek(pos, SEEK_SET);
  89.              ch = read_char();
  90.              pos += ch+14;
  91.              continue;
  92.           default:
  93.              record->method = 0;
  94.        }
  95.        break;
  96.     }
  97.     read_string(name);
  98.     seek(pos+15, SEEK_SET);
  99.     record->packed_size = read_long()+29;                             // 15
  100.     fill_date(record);                                                 // 19
  101.     fill_time(record);                                                 // 21
  102.     record->crc = (unsigned int)read_int();                          // 23
  103.     record->unpacked_size = read_long();                             // 25
  104.     pos+=record->packed_size;
  105.  
  106.     return 0;
  107. }
  108. #endif
  109. /****************************************************************/
  110. #if SUPPORT_ARJ
  111. int ARC_HANDLE::get_record_arj(ARC_RECORD *record, char *name)
  112. {
  113.     int ch;
  114.     long pos2, old_pos;
  115.     int  fn_len;
  116.  
  117.     if (isFirst)
  118.     {
  119.         pos2 = pos + 34;
  120.         seek(pos2, SEEK_SET);                          // archive name starts here
  121.         pos = pos2 + 8;
  122.         while (read_char() > 0)                       // file name
  123.             pos++;
  124.         while (read_char() > 0)                       // comment
  125.             pos++;
  126.         isFirst = FALSE;
  127.     }
  128.     old_pos = pos;
  129.  
  130.     seek(pos+5, SEEK_SET);
  131.     ch = read_char();
  132.     if (ch == 0 || ch == 26)
  133.         return EOF;
  134.     else if (ch == 4 && !is_self)
  135.         version = 60;
  136.  
  137.     seek(pos+8, SEEK_SET);
  138.     ch = read_char();
  139.     if (ch & 0x01)
  140.         record->encrypted = TRUE;
  141.  
  142.     ch = read_char();                                                 // 9
  143.     switch (ch)
  144.     {
  145.         case EOF:
  146.             return EOF;
  147.         case 0:
  148.             record->method = 1; break;
  149.         case 1: case 2: case 3: case 4:
  150.             record->method = 17 + ch;  break;
  151.         default:
  152.             record->method = 0;
  153.     }
  154.  
  155.     seek(pos+12, SEEK_SET);
  156.     fill_time(record);                                                 // 12
  157.     fill_date(record);                                                 // 14
  158.     record->packed_size   = read_long();                             // 16
  159.     record->unpacked_size = read_long();                             // 20
  160.     record->crc = read_long();                                         // 24
  161.  
  162.     seek(pos+30, SEEK_SET);
  163.     record->attrib = read_long();                                     // 30
  164.  
  165.     fn_len = read_string(name);                                      // 34
  166.     while (read_char() > 0)       // comment
  167.         fn_len++;
  168.  
  169.     pos += record->packed_size + fn_len + 42;
  170.  
  171.     if (pos <= old_pos || pos > old_pos+100000000)
  172.         return -2;
  173.     return 0;
  174. }
  175. #endif
  176. /****************************************************************/
  177. #if SUPPORT_DWC
  178. int ARC_HANDLE::get_record_dwc(ARC_RECORD *record, char *name)
  179. {
  180.     int ch;
  181.  
  182.     if (pos == 0)
  183.     {
  184.         pos = -2;
  185.         while (pos > -256)
  186.         {
  187.             seek(pos, SEEK_END);
  188.             if (read_char() == 'D')
  189.             {
  190.                 seek(pos-4, SEEK_END);
  191.                 // number of embedded files
  192.                 hold_n = read_long();
  193.                 pos = seek(0, SEEK_CUR) - 24 - hold_n*34;
  194.                 if (pos < 0)
  195.                     return -2;
  196.                 goto around;
  197.             }
  198.             pos--;
  199.         }
  200.         return -2;
  201.     }
  202. around:
  203.     hold_n--;
  204.     if (hold_n < 0)
  205.         return EOF;
  206.     seek(pos, SEEK_SET);
  207.     read_string(name);
  208.     seek(pos+13, SEEK_SET);
  209.     record->unpacked_size = read_long();                             // 13
  210.     my_localtime(read_long(), record);                                 // 17
  211.     record->packed_size = read_long();                                 // 21
  212.     seek(pos+29, SEEK_SET);
  213.     ch = read_char();
  214.     if (ch == 1)
  215.         record->method = 3;
  216.     else if (ch == 2)
  217.         record->method = 1;
  218.     else
  219.         record->method = 0;
  220.     seek(pos+32, SEEK_SET);
  221.     record->crc = (unsigned int)read_int();
  222.     pos+=34;
  223.     return 0;
  224. }
  225. #endif
  226. /****************************************************************/
  227. #if SUPPORT_HA
  228. int ARC_HANDLE::get_record_ha(ARC_RECORD *record, char *name)
  229. {
  230.     long old_pos;
  231.     int  ch, ch2;
  232.     int  fn_len;
  233.     char path[FLENGTH];
  234.     char file_name[FLENGTH];
  235.     char *ptr;
  236.  
  237.     if (pos == 0)
  238.         pos = 4;
  239.  
  240.     old_pos = pos;
  241.     seek(pos, SEEK_SET);
  242.     ch = read_char();
  243.     if (ch == EOF)
  244.         return EOF;
  245.     else if (ch == 32)
  246.         record->method = 1;    /* Stored */
  247.     else if (ch == 33)
  248.         record->method = 31;   /* ASC */
  249.     else if (ch == 34)
  250.         record->method = 32;   /* HSC */
  251.     else
  252.         record->method = 0;    /* Unknown */
  253.  
  254.     record->packed_size = read_long();                                 // 1
  255.     record->unpacked_size = read_long();                             // 5
  256.     record->crc = read_long();                                         // 9
  257.     my_localtime(read_long(), record);                                 // 13
  258.     read_string(path);                                                 // 17
  259.     read_string(file_name);                                          // 17+path
  260.     read_int();
  261.     record->attrib = read_char();
  262.  
  263.     pos += record->packed_size + strlen(path) + strlen(file_name) + 22;
  264.  
  265.     strcpy(name, path);
  266.     if (name[0] != '\0')
  267.     {
  268.         /* Not sure what this is all about, but seems to be necessary */
  269.         if (name[strlen(name)-1] == -1)
  270.             name[strlen(name)-1] = '\0';
  271.         append_backslash(name);
  272.     }
  273.     strcat(name, file_name);
  274.  
  275.     if (pos <= old_pos || pos > old_pos+100000000)
  276.         return -2;
  277.  
  278.     return 0;
  279. }
  280. #endif
  281. /****************************************************************/
  282. #if SUPPORT_HAP
  283. int ARC_HANDLE::get_record_hap(ARC_RECORD *record, char *name)
  284. {
  285.     long old_pos;
  286.     int  ch, ch2;
  287.     int  fn_len;
  288.     char path[FLENGTH];
  289.     char file_name[FLENGTH];
  290.     char *ptr;
  291.  
  292.     if (pos == 0)
  293.         pos = 15;
  294.  
  295.     old_pos = pos;
  296.     seek(pos, SEEK_SET);
  297.     ch = read_char();
  298.     if (ch == EOF)
  299.         return EOF;
  300.  
  301.     seek(pos+4, SEEK_SET);
  302.     record->packed_size = read_long();                                 // 4
  303.     seek(pos+17, SEEK_SET);
  304.     record->attrib = read_char();                                     // 16
  305.     fill_time(record);                                                 // 17
  306.     fill_date(record);                                                 // 19
  307.     seek(pos+22, SEEK_SET);
  308.     record->unpacked_size = read_long();                             // 22
  309.     read(name, 12);                                                  // 26
  310.     name[12] = '\0';
  311.     seek(pos+39, SEEK_SET);
  312.     ch = read_char();                                                 // 39
  313.     if (ch == 21)
  314.         record->method = 1;      /* Stored */
  315.     else if (ch == 22)
  316.         record->method = 34;     /* Learned */
  317.     else
  318.         record->method = 0;      /* Unknown */
  319.  
  320.     record->crc = 0;
  321.     pos += record->packed_size + 40;
  322.  
  323.     if (pos <= old_pos || pos > old_pos+100000000)
  324.         return -2;
  325.  
  326.     return 0;
  327. }
  328. #endif
  329. /****************************************************************/
  330. #if SUPPORT_HPK
  331. int ARC_HANDLE::get_record_hpk(ARC_RECORD *record, char *name)
  332. {
  333.     int ch, ch2, n;
  334.  
  335.     if (pos == 0)
  336.     {
  337.         pos = -3;
  338.         while (pos > -256)
  339.         {
  340.             seek(pos, SEEK_END);
  341.             if (read_char() == 'H')
  342.             {
  343.                 seek(pos-9, SEEK_END);
  344.                 // number of embedded files
  345.                 hold_n = read_int();
  346.                 ch = read_int();
  347.                 pos = seek(- 6L - ch, SEEK_CUR);
  348.                 if (pos < 0)
  349.                     return -2;
  350.  
  351.                 // Find the front of the file names, there should be a better way
  352.  
  353.                 n = hold_n;
  354.                 while (n > 0)
  355.                 {
  356.                     ch = read_char();                                  // 0
  357.                     ch2 = read_char();                                  // 1
  358.                     (void)read_long();
  359.  
  360.                     if (ch2 & 0x10)
  361.                         read_int();
  362.  
  363.                     if (ch2 & 0x80)
  364.                         read_long();
  365.                     else
  366.                         read_int();
  367.  
  368.                     if (ch2 & 0x40)
  369.                         read_long();
  370.                     else
  371.                         read_int();
  372.  
  373.                     if (ch2 & 0x01)
  374.                         read_int();
  375.                     n--;
  376.                 }
  377.  
  378.                 trailer_pos = seek(0L, SEEK_CUR);
  379.                 goto around;
  380.             }
  381.             pos--;
  382.         }
  383.         return -2;
  384.     }
  385. around:
  386.     hold_n--;
  387.     if (hold_n < 0)
  388.         return EOF;
  389.     /* not sure exactly what the deal with the attributes is */
  390.     seek(pos-1, SEEK_SET);
  391.     record->attrib = read_char();
  392.     ch = read_char();
  393.     ch2 = read_char();                                                 // 1
  394.     record->method = 33;
  395.     record->crc = 0;
  396.  
  397.     if (ch2 & 0x10)                      /* attributes */
  398.         read_int();
  399.     else
  400.         record->attrib = 0x00;
  401.  
  402.     my_localtime(read_long(), record);                                 // 2
  403.  
  404.     if (ch2 & 0x80)
  405.         record->unpacked_size = read_long();
  406.     else
  407.         record->unpacked_size = (unsigned int)read_int();
  408.  
  409.     if (ch2 & 0x40)
  410.         record->packed_size = read_long();
  411.     else
  412.         record->packed_size = (unsigned int)read_int();
  413.  
  414.     if (ch2 & 0x01)
  415.         read_int();   /* Something having to do with comments */
  416.  
  417.     seek(trailer_pos, SEEK_SET);
  418.     read_string(name);
  419.     trailer_pos = seek(0, SEEK_CUR);
  420.  
  421.     pos += 10;
  422.     if (ch2 & 0x10)
  423.         pos += 2;
  424.     if (ch2 & 0x40)
  425.         pos += 2;
  426.     if (ch2 & 0x80)
  427.         pos += 2;
  428.     if (ch2 & 0x01)
  429.     {
  430.         pos += 2;
  431.         goto around;
  432.     }
  433.     return 0;
  434. }
  435. #endif
  436. /****************************************************************/
  437. #if SUPPORT_HYP
  438. int ARC_HANDLE::get_record_hyp(ARC_RECORD *record, char *name)
  439. {
  440.     long old_pos;
  441.     int  ch, ch2;
  442.     int  fn_len;
  443.     char *ptr;
  444.  
  445.     old_pos = pos;
  446.     seek(pos+1, SEEK_SET);
  447.     ch = read_char();
  448.     if (ch == EOF)
  449.         return EOF;
  450.     else if (ch == 'H')
  451.         record->method = 30;   /* Hypered */
  452.     else
  453.         record->method = 1;    /* Stored */
  454.  
  455.     seek(pos+4, SEEK_SET);
  456.     record->packed_size = read_long();                                 // 4
  457.     record->unpacked_size = read_long();                             // 8
  458.     fill_time(record);                                                 // 12
  459.     fill_date(record);                                                 // 14
  460.     seek(pos+20, SEEK_SET);
  461.     record->attrib = read_char();                                     // 20
  462.     fn_len = read_char();                                             // 21
  463.     if (fn_len >= SZ_NAME || fn_len < 0)
  464.         return -2;
  465.     read(name, fn_len);
  466.     name[fn_len] = '\0';
  467.  
  468.     record->crc = 0;
  469.  
  470.     pos += record->packed_size + fn_len + 22;
  471.  
  472.     if (pos <= old_pos || pos > old_pos+100000000)
  473.         return -2;
  474.  
  475.     return 0;
  476. }
  477. #endif
  478. /****************************************************************/
  479. #if SUPPORT_LBR
  480. int ARC_HANDLE::get_record_lbr(ARC_RECORD *record, char *name)
  481. {
  482.     DATE lbr_date;
  483.     long old_pos;
  484.     char temp[255];
  485.     int ch;
  486.  
  487.     if (pos == 0)
  488.     {
  489.         seek(pos+14, SEEK_SET);
  490.         hold_n = read_char() + 2;
  491.         pos = 32;
  492.     }
  493.  
  494.     old_pos = pos;
  495.     if (hold_n == 0)
  496.         return EOF;
  497.  
  498.     for (;;)
  499.     {
  500.         seek(pos, SEEK_SET);
  501.         ch = read_char();
  502.         if (ch != 0)
  503.         {
  504.             pos+=32;
  505.             hold_n--;
  506.             if (hold_n == 0)
  507.                 return EOF;
  508.         }
  509.         else
  510.             break;
  511.     }
  512.  
  513.     seek(pos+1, SEEK_SET);       /* Name */
  514.     read(name, 8);
  515.     name[8] = '\0';
  516.     rtrim(name);
  517.     strcat(name, ".");
  518.     read(temp, 3);
  519.     temp[3] = '\0';
  520.     strcat(name, temp);
  521.  
  522.     seek(pos+14, SEEK_SET);
  523.     ch = read_char();
  524.     seek(pos+26, SEEK_SET);
  525.     record->packed_size = ch * 128 - read_char();
  526.     record->unpacked_size = record->packed_size;
  527.  
  528.     seek(pos+16, SEEK_SET);
  529.     record->crc = (unsigned int)read_int();
  530.     {
  531.         lbr_date.year  = 1977;
  532.         lbr_date.month = 12;
  533.         lbr_date.day   = 31;
  534.         date_add(&lbr_date, &record->date, read_int());          /* 18*/
  535.     }
  536.     seek(pos+22, SEEK_SET);
  537.     fill_time(record);
  538.  
  539.     hold_n--;
  540.     record->method = 1;     /* Stored */
  541.     pos+=32;
  542.  
  543.     if (pos <= old_pos || pos > old_pos+100000000)
  544.         return -2;
  545.     return 0;
  546. }
  547. #endif;
  548. /****************************************************************/
  549. #if SUPPORT_LZS || SUPPORT_LZH
  550. int ARC_HANDLE::get_record_lzh(ARC_RECORD *record, char *name)
  551. {
  552.     long old_pos;
  553.     int ch, ch2;
  554.     unsigned char d1;
  555.     char string[255];
  556.     char *ptr;
  557.  
  558.     old_pos = pos;
  559.     seek(pos+4, SEEK_SET);
  560.  
  561.  /* Additional version check */
  562.     ch = read_char();
  563.     if (ch == 'h')
  564.     {
  565.         if (version < 2)      /* At least Lharc 1.xx */
  566.             version = 2;
  567.     }
  568.  
  569.  /* Archive method */
  570.     ch = read_char();
  571.     switch(ch)
  572.     {
  573.         case EOF:
  574.             return EOF;
  575.         case '0':
  576.             record->method = 1;
  577.             break;
  578.         case '1':
  579.             record->method = 9;
  580.             break;
  581.         case '4':
  582.         case '5':
  583.             if (type == LZH)
  584.             {
  585.                 if (ch == '5')
  586.                     record->method = 10;
  587.                 else
  588.                     record->method = 22;
  589.  
  590.                 if (version < 3)    /* At least lharc 2.x */
  591.                     version = 3;
  592.             }
  593.             else
  594.             {
  595.                 if (ch == '5')
  596.                     record->method = 11;
  597.                 else
  598.                     record->method = 35;
  599.             }
  600.             break;
  601.         default:
  602.             return EOF;
  603.     }
  604.  
  605.     seek(pos+7, SEEK_SET);
  606.     record->packed_size   = read_long();
  607.     record->unpacked_size = read_long();
  608.  
  609.     seek(pos+20, SEEK_SET);
  610.     ch = read_char();
  611.  
  612.     d1 = 0;
  613.     if (ch < 2)     /* Header level of 0 or 1 */
  614.     {
  615.         seek(pos+15, SEEK_SET);
  616.         fill_time(record);
  617.         fill_date(record);
  618.         if (ch == 0)
  619.             record->attrib = read_int();
  620.         seek(pos+21, SEEK_SET);
  621.         d1 = read_char();
  622.         read(string, d1);
  623.         string[d1] = '\0';
  624.         record->crc = (unsigned int)read_int();
  625.         if (ch == 1)         /* Header level of 1 */
  626.         {
  627.             pos += 25 + d1;
  628.  
  629.             read_char();
  630.             ch2 = read_int();
  631.  
  632.             record->attrib = 0x00;
  633.             while (ch2 > 0)
  634.             {
  635.                 ch = read_char();
  636.                 if (ch == 0x02)
  637.                 {
  638.                     if (ch2-4 >= SZ_NAME || ch2-4 < 0)
  639.                         return -2;
  640.                     read(record->path, ch2-4);
  641.                     record->path[ch2-4] = '\0';
  642.                     read_char();
  643.                 }
  644.                 else if (ch == 0x40)
  645.                 {
  646.                     record->attrib = read_char();
  647.                 }
  648.                 pos+=ch2;
  649.                 seek(pos, SEEK_SET);
  650.                 record->packed_size -= ch2;
  651.                 ch2 = read_int();
  652.             }
  653.  
  654.             pos += 2 + record->packed_size;
  655.         }
  656.         else
  657.             pos+= 24 + d1 +record->packed_size;
  658.     }
  659.     else if (ch == 2)
  660.     {
  661.         seek(pos+15, SEEK_SET);
  662.         my_localtime(read_long(), record);
  663.         seek(pos+21, SEEK_SET);
  664.         record->crc = (unsigned int)read_int();
  665.         seek(pos+24, SEEK_SET);
  666.  
  667.         pos += 24;
  668.         ch2 = read_int();
  669.         while (ch2 > 0)
  670.         {
  671.             ch = read_char();
  672.             if (ch == 1)
  673.             {
  674.                 read(string, ch2-3);
  675.                 string[ch2-3] = '\0';
  676.             }
  677.             else if (ch == 0x02)
  678.             {
  679.                 if (ch2-4 >= SZ_NAME || ch2-4 < 0)
  680.                     return -2;
  681.                 read(record->path, ch2-4);
  682.                 record->path[ch2-4] = '\0';
  683.                 read_char();
  684.             }
  685.             else if (ch == 0x40)
  686.             {
  687.                 record->attrib = read_char();
  688.             }
  689.             pos+=ch2;
  690.             seek(pos, SEEK_SET);
  691.             ch2 = read_int();
  692.         }
  693.  
  694.         pos+= 2 + record->packed_size;
  695.  
  696.         if (version < 3)
  697.             version = 3;
  698.     }
  699.     else
  700.         return -2;
  701.  
  702.     /* Somehow Amiga .LZHs have the ability to stuff some sort of
  703.        comment into the name, this should take care of that */
  704.     {
  705.        if ((ptr = strchr(string, ' ')) != NULL)
  706.            *ptr = '\0';
  707.  
  708.        if (strlen(string) > 80)
  709.            string[79] = '\0';
  710.        strcpy(name, string);
  711.     }
  712.  
  713.     if (pos <= old_pos || pos > old_pos+100000000)
  714.        return -2;
  715.     return 0;
  716. }
  717. #endif
  718. /****************************************************************/
  719. #if SUPPORT_MD
  720. int ARC_HANDLE::get_record_md(ARC_RECORD *record, char *name)
  721. {
  722.     long old_pos;
  723.     int  ch, ch2;
  724.     int  fn_len;
  725.     char path[FLENGTH];
  726.     char file_name[FLENGTH];
  727.     char *ptr;
  728.  
  729.     old_pos = pos;
  730.     seek(pos+24, SEEK_SET);
  731.     ch = read_char();
  732.     if (ch == EOF)
  733.         return EOF;
  734.     else if (ch == 0)
  735.         record->method = 1;    /* Stored */
  736.     else if (ch == 1)
  737.         record->method = 36;   /* LZW13 */
  738.     else
  739.         record->method = 0;    /* Unknown */
  740.  
  741.     record->unpacked_size = read_long();                             // 25
  742.     record->packed_size = read_long();                                 // 29
  743.     record->attrib = read_int();                                     // 33
  744.     fill_time(record);                                                 // 35
  745.     fill_date(record);                                                 // 37
  746.     record->crc = (unsigned int)read_int();                          // 39
  747.     ch = read_char();                                                 // 41
  748.     read(name, ch);                                                  // 42
  749.     name[ch] = '\0';
  750.  
  751.     pos += record->packed_size + 122;
  752.  
  753.     if (pos <= old_pos || pos > old_pos+100000000)
  754.         return -2;
  755.  
  756.     return 0;
  757. }
  758. #endif
  759. /****************************************************************/
  760. #if SUPPORT_PAK || SUPPORT_ARC
  761. int ARC_HANDLE::get_record_pak(ARC_RECORD *record, char *name)
  762. {
  763.     long old_pos;
  764.     int ch, ch2;
  765.     long next;
  766.     char string[255];
  767.  
  768.     old_pos = pos;
  769.     seek(pos+1, SEEK_SET);
  770.  
  771.  /* Archive method */
  772.     ch = read_char();
  773.     switch(ch)
  774.     {
  775.         case 0:
  776.             return EOF;
  777.         case 1:
  778.         case 2:
  779.             record->method = 1; break;
  780.         case 3:
  781.             record->method = 7; break;
  782.         case 4:
  783.             record->method = 6; break;
  784.         case 5: case 6:
  785.             record->method = 2;  break;
  786.         case 7: case 8:
  787.             record->method = 3; break;
  788.         case 9:
  789.             if (version == 47)
  790.                 version = 49;
  791.             record->method = 4;
  792.             break;
  793.         case 10:
  794.             record->method = 5; break;
  795.         case 11:
  796.             if (version >= 47 || version <= 49)
  797.                 version = 50;
  798.             record->method = 8;
  799.             break;
  800.         default:
  801.             return -2;
  802.     }
  803.  
  804.  /* name */
  805.     read_string(name);
  806.  
  807.     seek(pos+15, SEEK_SET);
  808.     record->packed_size = read_long();
  809.  
  810.     fill_date(record);                                                      // 19
  811.     fill_time(record);                                                      // 21
  812.     record->crc = (unsigned int)read_int();                               // 23
  813.     record->unpacked_size = read_long();                                  // 25
  814.  
  815.     pos += 29 + record->packed_size;
  816.  
  817.     if (pos <= old_pos || pos > old_pos+100000000)
  818.        return -2;
  819.  
  820.     /* Go after the trailer info */
  821.     while (trailer_pos > 0)
  822.     {
  823.         seek(trailer_pos, SEEK_SET);
  824.         ch = read_char();
  825.         if (ch == 0 || ch == EOF)
  826.             trailer_pos = -1;
  827.         else
  828.         {
  829.             ch2 = read_int();
  830.             next = read_long();
  831.             if (ch2 > rec_number)
  832.                break;
  833.             if (ch2 == rec_number && ch == 2)
  834.             {
  835.                 if (next >= SZ_NAME || next < 0)
  836.                     return -2;
  837.                 read(record->path, next);
  838.                 record->path[next] = '\0';
  839.                 trailer_pos += next + 8;
  840.                 break;
  841.             }
  842.             trailer_pos += next + 1;
  843.             seek(trailer_pos, SEEK_SET);
  844.         }
  845.     }
  846.     return 0;
  847. }
  848. #endif
  849. /****************************************************************/
  850. #if SUPPORT_RAR
  851. int ARC_HANDLE::get_record_rar(ARC_RECORD *record, char *name)
  852. {
  853.     long old_pos;
  854.     int  ch, flags;
  855.     int  fn_len;
  856.     int  header_size;
  857.     char *ptr;
  858.  
  859.  
  860.     if (version == 81)                               /* RAR 1.50 > */
  861.     {
  862.         if (isFirst)
  863.         {
  864.             seek(pos + 12L, SEEK_SET);
  865.             pos += read_int() + 7;
  866.             isFirst = FALSE;
  867.         }
  868.  
  869.         old_pos = pos;
  870.         seek(pos, SEEK_SET);
  871.         if (read_char() == EOF)
  872.             return EOF;
  873.         seek(pos, SEEK_SET);
  874.  
  875.         read_int();     /* header CRC */
  876.         read_char();    /* header type */
  877.         flags = read_int();                                          // 3
  878.         header_size = read_int();                                     // 5
  879.         record->packed_size = read_long();                             // 7
  880.         record->unpacked_size = read_long();                         // 11
  881.         read_char();    /* Host operating system */
  882.         record->crc = read_long();                                     // 16
  883.         fill_time(record);                                             // 20
  884.         fill_date(record);                                             // 22
  885.         read_char();    /* version needed to extract */              // 24
  886.         ch = read_char();                                             // 25
  887.         if (ch == 0)
  888.             record->method = 1;      /* Stored */
  889.         else if (ch >= '1' && ch <= '5')
  890.             record->method = 36 + ch - '0';
  891.         fn_len = read_int();                                         // 26
  892.         if (fn_len >= SZ_NAME || fn_len < 0)
  893.             return -2;
  894.         record->attrib = read_long();                                 // 28
  895.         read(name, fn_len);                                          // 32
  896.         name[fn_len] = '\0';
  897.         /* Comment goes here if flags & 0x08 */
  898.  
  899.         pos += record->packed_size + header_size;
  900.  
  901.     }
  902.     else                                           /* RAR 1.40 < */
  903.     {
  904.         if (isFirst)
  905.         {
  906.             seek(pos + 4L, SEEK_SET);
  907.             pos += read_int();
  908.             isFirst = FALSE;
  909.         }
  910.  
  911.         old_pos = pos;
  912.         seek(pos, SEEK_SET);
  913.         if (read_char() == EOF)
  914.             return EOF;
  915.         seek(pos, SEEK_SET);
  916.         record->packed_size = read_long();                             // 0
  917.         record->unpacked_size = read_long();                         // 4
  918.         record->crc = (unsigned int)read_int();                      // 8
  919.         seek(pos+12, SEEK_SET);
  920.         fill_time(record);                                             // 12
  921.         fill_date(record);                                             // 14
  922.         record->attrib = read_char();                                 // 16
  923.         flags = read_char();                                         // 17
  924.         read_char();
  925.         fn_len = read_char();                                         // 19
  926.         if (fn_len >= SZ_NAME || fn_len < 0)
  927.             return -2;
  928.         ch = read_char();                                             // 20
  929.         if (ch == 0)
  930.             record->method = 1;      /* Stored */
  931.         else if (ch >= 1 && ch <= 5)
  932.             record->method = 36 + ch;
  933.  
  934.         read(name, fn_len);                                          // 21
  935.         name[fn_len] = '\0';
  936.         if (flags & 0x08)
  937.             ch = read_int() + 2;       /* length of file comment */
  938.         else
  939.             ch = 0;
  940.  
  941.         pos += record->packed_size + fn_len + ch + 21;
  942.     }
  943.  
  944.     if (pos <= old_pos || pos > old_pos+100000000)
  945.         return -2;
  946.  
  947.     return 0;
  948. }
  949. #endif
  950. /****************************************************************/
  951. #if SUPPORT_SQZ
  952. int ARC_HANDLE::get_record_sqz(ARC_RECORD *record, char *name)
  953. {
  954.     long old_pos;
  955.     int  ch, ch2;
  956.     int  fn_len;
  957.     char *ptr;
  958.  
  959.     if (pos == 0)
  960.     {
  961.         pos = 8;
  962.         seek(pos, SEEK_SET);
  963.         ch = read_char();
  964.         if (ch == 1)       /* header, skip it */
  965.         {
  966.             ch2 = read_int();
  967.             pos += ch2 + 3;
  968.         }
  969.         else
  970.             pos = 8;
  971.     }
  972.     old_pos = pos;
  973.     seek(pos, SEEK_SET);
  974.     fn_len = read_char() - 18;
  975.     if (fn_len >= SZ_NAME || fn_len < 0)
  976.         return EOF;     /* Not sure what the true EOF condition is yet */
  977.     read_char();                           /* Not sure what this byte is yet */
  978.     ch = read_char();
  979.     switch (ch)
  980.     {
  981.         case EOF:
  982.             return EOF;
  983.         case 0:
  984.             record->method = 1;
  985.             break;
  986.         case 1: case 2: case 3: case 4:
  987.             record->method = 17 + ch;
  988.             break;
  989.         default:
  990.             record->method = 0;
  991.             break;
  992.     }
  993.     record->packed_size = read_long();                                 // 3
  994.     record->unpacked_size = read_long();                             // 7
  995.     fill_time(record);                                                 // 11
  996.     fill_date(record);                                                 // 13
  997.     record->attrib = read_char();                                     // 15
  998.     record->crc = read_long();                                         // 16
  999.  
  1000.     read(name, fn_len);
  1001.     name[fn_len] = '\0';
  1002.  
  1003.     pos += record->packed_size + fn_len + 20;
  1004.  
  1005.     /* Remove double backslashes from the name, I don't know why sqz does this */
  1006.     while ((ptr = strchr(name, '/')) != NULL)
  1007.         *ptr = '\\';
  1008.     while ((ptr = strstr(name, "\\\\")) != NULL)
  1009.         memmove(ptr, ptr+1, strlen(ptr));
  1010.  
  1011.     if (pos <= old_pos || pos > old_pos+100000000)
  1012.         return -2;
  1013.  
  1014.     return 0;
  1015. }
  1016. #endif
  1017. /****************************************************************/
  1018. #if SUPPORT_ZIP
  1019. int ARC_HANDLE::get_record_zip(ARC_RECORD *record, char *name)
  1020. {
  1021.     long old_pos;
  1022.     long sig;
  1023.     int ch, ch2;
  1024.     int fn_len;
  1025.  
  1026.     /* Determine front of Central dir structure */
  1027.  
  1028.     if (isFirst)
  1029.     {
  1030.         pos = -16;
  1031.         while (seek(pos, SEEK_END) > 0)
  1032.         {
  1033.             sig = read_long();
  1034.             if (sig == 0x06054B50)
  1035.             {
  1036.                 seek(12, SEEK_CUR);
  1037.                 pos = read_long();
  1038.                 break;
  1039.             }
  1040.             pos--;
  1041.         }
  1042.         if (pos < 0)
  1043.             return -2;
  1044.         isFirst = FALSE;
  1045.     }
  1046.  
  1047.     old_pos = pos;
  1048.     seek(pos, SEEK_SET);
  1049.     sig = read_long();             /* Read centralized dir struct signature */
  1050.     if (sig != 0x02014B50)
  1051.         return EOF;
  1052.  
  1053.     ch = read_char();      /* version made by */
  1054.     switch (ch)
  1055.     {
  1056.         case 10:
  1057.             if (version < 6 || version == 82)
  1058.                 version = 6;
  1059.             break;
  1060.         case 11:
  1061.             if (version < 7 || version == 82)
  1062.                 version = 7;
  1063.             break;
  1064.         case 20:
  1065.             if (version < 53 || version == 82)
  1066.                 version = 53;
  1067.             break;
  1068.         case 0:
  1069.             version = 0;
  1070.             return EOF;
  1071.         default:
  1072.             version = 82;           /* Unknown zip type */
  1073.             break;
  1074.     }
  1075.  
  1076.     read_char();       /* Host OS, Ver and OS needed to extact */
  1077.     read_char();
  1078.     read_char();
  1079.     ch2 = read_int();  /* General purpose bit flag */
  1080.  
  1081.     /* Archive method */
  1082.     ch = read_int();
  1083.     switch(ch)
  1084.     {
  1085.         case 0:                               /* Stored */
  1086.             record->method = 1; break;
  1087.         case 1:                               /* Shrunk */
  1088.             record->method = 12; break;
  1089.         case 2: case 3: case 4: case 5:       /* Reduced */
  1090.             record->method = 11+ch; break;
  1091.         case 6:                               /* Implode */
  1092.             record->method = 17;
  1093. //              /* at least 1.0x since there is imploding done */
  1094. //              if (version < 6)
  1095. //                  version = 6;
  1096.             break;
  1097.         case 8:
  1098. //              if (version < 53)
  1099. //                  version = 53;
  1100.             switch (ch2 & 0x06)
  1101.             {
  1102.                 case 0:
  1103.                     record->method = 26;  break;   /* Deflated */
  1104.                 case 2:
  1105.                     record->method = 27;  break;   /* Deflated -EX */
  1106.                 case 4:
  1107.                     record->method = 28;  break;   /* Deflated -EF */
  1108.                 case 6:
  1109.                     record->method = 29;  break;   /* Deflated -ES */
  1110.             }
  1111.             if (ch2 & 0x01)
  1112.                 record->encrypted = TRUE;
  1113.             break;
  1114.         default:
  1115.             record->method = 0;    /* Unknown */
  1116.     }
  1117.     fill_time(record);                                                   // 12
  1118.     fill_date(record);                                                   // 14
  1119.     record->crc = read_long();                                           // 16
  1120.     record->packed_size   = read_long();                               // 20
  1121.     record->unpacked_size = read_long();                               // 24
  1122.     fn_len = read_int();                                               // 28
  1123.     if (fn_len >= SZ_NAME || fn_len < 0)
  1124.         return -2;
  1125.     ch    = read_int();    /* Extra field len */                           // 30
  1126.     ch2 = read_int();    /* File Comment len */                           // 32
  1127.     read_long();        /* Disk Number start and int file attr */       // 34
  1128.     record->attrib = read_long();                                       // 38
  1129.     read_long();        /* Position of local header */                   // 42
  1130.     read(name, fn_len);                                                // 46
  1131.     name[fn_len] = '\0';
  1132.     pos = seek(ch + ch2, SEEK_CUR); /* Skip over extra field and comment */
  1133.  
  1134.     if (pos <= old_pos || pos > old_pos+100000000)
  1135.         return -2;
  1136.     return 0;
  1137.  
  1138. #if 0
  1139.     old_pos = pos;
  1140.  
  1141.     seek(pos+2, SEEK_SET);
  1142.     if (read_char() == 1)
  1143.     {
  1144.         seek(pos+4, SEEK_SET);
  1145.         if (read_char() == 11)
  1146.             if (version < 7 )
  1147.                 version = 7;
  1148.         return EOF;
  1149.     }
  1150.  
  1151.     seek(pos+6, SEEK_SET);
  1152.     if ((ch2 = read_char()) == EOF)
  1153.         return EOF;
  1154.  
  1155.     seek(pos+8, SEEK_SET);
  1156.     if ((ch = read_char()) == EOF)
  1157.         return EOF;
  1158.  
  1159.     /* Archive method */
  1160.     switch(ch)
  1161.     {
  1162.         case 0:                               /* Stored */
  1163.             record->method = 1; break;
  1164.         case 1:                               /* Shrunk */
  1165.             record->method = 12; break;
  1166.         case 2: case 3: case 4: case 5:       /* Reduced */
  1167.             record->method = 11+ch; break;
  1168.         case 6:                               /* Implode */
  1169.             record->method = 17;
  1170.             /* at least 1.0x since there is imploding done */
  1171.             if (version < 6)
  1172.                 version = 6;
  1173.             break;
  1174.         case 8:
  1175.             if (version < 53)
  1176.                 version = 53;
  1177.             switch (ch2 & 0x06)
  1178.             {
  1179.                 case 0:
  1180.                     record->method = 26;  break;   /* Deflated */
  1181.                 case 2:
  1182.                     record->method = 27;  break;   /* Deflated -EX */
  1183.                 case 4:
  1184.                     record->method = 28;  break;   /* Deflated -EF */
  1185.                 case 6:
  1186.                     record->method = 29;  break;   /* Deflated -ES */
  1187.             }
  1188.             if (ch2 & 0x01)
  1189.                 record->encrypted = TRUE;
  1190.             break;
  1191.         default:
  1192.             record->method = 0;    /* Unknown */
  1193.     }
  1194.  
  1195.     read_char();                                                       // 9
  1196.     fill_time(record);                                                   // 10
  1197.     fill_date(record);                                                   // 12
  1198.     record->crc = read_long();                                           // 14
  1199.     record->packed_size   = read_long();                               // 18
  1200.     record->unpacked_size = read_long();                               // 22
  1201.     ch = read_int();                                                   // 26
  1202.     if (ch >= SZ_NAME || ch < 0)
  1203.         return -2;
  1204.     ch2 = read_int();                                                   // 28
  1205.     read(name, ch);                                                    // 30
  1206.     name[ch] = '\0';
  1207.  
  1208.     pos += 30+record->packed_size;
  1209.     pos += ch+ch2;
  1210.  
  1211.     if (pos <= old_pos || pos > old_pos+100000000)
  1212.         return -2;
  1213.     return 0;
  1214. #endif
  1215.  
  1216. }
  1217. #endif
  1218. /****************************************************************/
  1219. #if SUPPORT_ZOO
  1220. int ARC_HANDLE::get_record_zoo(ARC_RECORD *record, char *name)
  1221. {
  1222.     long old_pos;
  1223.     long next_pos;
  1224.     int  ch, ch2;
  1225.     char string[255];
  1226.  
  1227. top:
  1228.     if (pos == 0)
  1229.     {
  1230.         seek(pos+24, SEEK_SET);
  1231.         ch = read_char();
  1232.         if (ch == 34)
  1233.             version = 62;      /* 1.x */
  1234.         else
  1235.             version = 10;      /* 2.x */
  1236.  
  1237.         pos = ch+1;
  1238.     }
  1239. around:
  1240.     old_pos = pos;
  1241.  
  1242.     seek(pos+4, SEEK_SET);
  1243.     ch = read_char();
  1244.     switch (ch)
  1245.     {
  1246.         case 0:
  1247.            record->method = 1; break;          // stored
  1248.         case 1:
  1249.            record->method = 23; break;          // Normal
  1250.         case 2:
  1251.            record->method = 24;               // High
  1252.            if (version != 59)
  1253.                version = 51;                     // therefore ZOO 2.10
  1254.            break;
  1255.         case EOF:
  1256.             return EOF;
  1257.         default:
  1258.             record->method = 0; break;          // Unknown
  1259.     }
  1260.     next_pos = read_long()+1;
  1261.  
  1262.     seek(pos+13, SEEK_SET);
  1263.  
  1264.     fill_date(record);                                                   // 13
  1265.     fill_time(record);                                                   // 15
  1266.     record->crc = (unsigned int)read_int();                            // 17
  1267.     record->unpacked_size = read_long();                               // 19
  1268.     record->packed_size = read_long();                                   // 23
  1269.     if (record->packed_size == 0)
  1270.     {
  1271.         pos+=27;
  1272.         while ((ch = read_char())!=0xA7)
  1273.         {
  1274.             if (ch == EOF)
  1275.                 return EOF;
  1276.             pos++;
  1277.         }
  1278.         goto around;
  1279.     }
  1280.     seek(pos+29, SEEK_SET);
  1281.     if (read_char() == 1)
  1282.     {
  1283.         /* Deleted file */
  1284.         pos = next_pos;
  1285.         goto top;
  1286.     }
  1287.  
  1288.     seek(pos+37, SEEK_SET);
  1289.     read_string(string);
  1290.     seek(pos+55, SEEK_SET);
  1291.     ch = read_char();
  1292.     ch2= read_char();
  1293.  
  1294.     if (ch != 64)       // Not sure what this is all about yet
  1295.     {
  1296.         if (ch != 0)
  1297.         {
  1298.             if (ch >= SZ_NAME || ch < 0)
  1299.                 return -2;
  1300.             read(string, ch);
  1301.             string[ch] = '\0';
  1302.         }
  1303.         if (ch2 == 0)
  1304.             strcpy(name, string);
  1305.         else
  1306.         {
  1307.             read_string(name);
  1308.             strcat(name, "\\");
  1309.             strcat(name, string);
  1310.         }
  1311.     }
  1312.     else
  1313.         strcpy(name, string);
  1314.  
  1315.     pos = next_pos;
  1316.  
  1317.     if (pos <= old_pos || pos > old_pos+100000000)
  1318.         return -2;
  1319.  
  1320.     return 0;
  1321. }
  1322. #endif
  1323. /****************************************************************/
  1324. int ARC_HANDLE::get_record(AU *, ARC_RECORD *record)
  1325. {
  1326.     int  retCode;
  1327.     char name[SZ_NAME];
  1328.  
  1329.     record->method = 0;              /* unknown until otherwise */
  1330.     record->name[0] = '\0';
  1331.     record->path[0] = '\0';
  1332.     record->encrypted = FALSE;
  1333.     rec_number++;
  1334.  
  1335.     switch (type)
  1336.     {
  1337. #if SUPPORT_ARC
  1338.        case ARC7:
  1339.           retCode = get_record_arc7(record, name);
  1340.           break;
  1341. #endif
  1342. #if SUPPORT_ARJ
  1343.        case ARJ:
  1344.           retCode = get_record_arj(record, name);
  1345.           break;
  1346. #endif
  1347. #if SUPPORT_DWC
  1348.        case DWC:
  1349.           retCode = get_record_dwc(record, name);
  1350.           break;
  1351. #endif
  1352. #if SUPPORT_MD
  1353.        case MD:
  1354.           retCode = get_record_md(record, name);
  1355.           break;
  1356. #endif
  1357. #if SUPPORT_HA
  1358.        case HA:
  1359.           retCode = get_record_ha(record, name);
  1360.           break;
  1361. #endif
  1362. #if SUPPORT_HAP
  1363.        case HAP:
  1364.           retCode = get_record_hap(record, name);
  1365.           break;
  1366. #endif
  1367. #if SUPPORT_HPK
  1368.        case HPK:
  1369.           retCode = get_record_hpk(record, name);
  1370.           break;
  1371. #endif
  1372. #if SUPPORT_HYP
  1373.        case HYP:
  1374.           retCode = get_record_hyp(record, name);
  1375.           break;
  1376. #endif
  1377. #if SUPPORT_LBR
  1378.        case LBR:
  1379.           retCode = get_record_lbr(record, name);
  1380.           break;
  1381. #endif
  1382. #if SUPPORT_LZS || SUPPORT_LZH
  1383.        case LZS:
  1384.        case LZH:
  1385.           retCode = get_record_lzh(record, name);
  1386.           break;
  1387. #endif
  1388. #if SUPPORT_PAK || SUPPORT_ARC
  1389.        case PAK:
  1390.        case ARC:
  1391.           retCode = get_record_pak(record, name);
  1392.           break;
  1393. #endif
  1394. #if SUPPORT_RAR
  1395.        case RAR:
  1396.           retCode = get_record_rar(record, name);
  1397.           break;
  1398. #endif
  1399. #if SUPPORT_SQZ
  1400.        case SQZ:
  1401.           retCode = get_record_sqz(record, name);
  1402.           break;
  1403. #endif
  1404. #if SUPPORT_ZIP
  1405.        case ZIP:
  1406.           retCode = get_record_zip(record, name);
  1407.           break;
  1408. #endif
  1409. #if SUPPORT_ZOO
  1410.        case ZOO:
  1411.           retCode = get_record_zoo(record, name);
  1412.           break;
  1413. #endif
  1414.        default:                 /* not supported but known */
  1415.           return -3;
  1416.     }
  1417.  
  1418.     if (retCode == 0)
  1419.     {
  1420.         if (record->path[0] == '\0')
  1421.         {
  1422.             fix_path(name);
  1423.             split_file(name, record->path, record->name);
  1424.         }
  1425.         else
  1426.             strcpy(record->name, name);
  1427.  
  1428.         if (record->packed_size < 0 || record->unpacked_size < 0)
  1429.             return -2;
  1430.     }
  1431.     return retCode;
  1432. }
  1433.  
  1434.